/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sqlserver_common.h                                            */
/*  NOTE      =                                                               */
/*  DATE      = 2014/09/30 by zhengxd                                         */
/******************************************************************************/
#ifndef _SQLSERVER_COMMON_H_
#define _SQLSERVER_COMMON_H_

#include "./sqlserver_core.h"

/* RPC数据还是COLMETADATA */
#define MSSQL_RPC                   0
#define MSSQL_COLMETA               1

/* TDS版本猜想 */
#define MSSQL_TDS_VER_UNKNOWN       0
#define MSSQL_TDS_VER_LITTLE        1
#define MSSQL_TDS_VER_BIG           2

/* TDS版本号定义 */
#define MSSQL_TDS_VER_NULL          0    /* 未知 */
#define MSSQL_TDS_VER_70            1    /* TDS 7.0 */
#define MSSQL_TDS_VER_71            2    /* TDS 7.1 */
#define MSSQL_TDS_VER_71R1          3    /* TDS 7.1R1 */
#define MSSQL_TDS_VER_72            4    /* TDS 7.2 */
#define MSSQL_TDS_VER_73            5    /* TDS 7.2 */
#define MSSQL_TDS_VER_73A           6    /* TDS 7.3A */
#define MSSQL_TDS_VER_73B           7    /* TDS 7.B */
#define MSSQL_TDS_VER_74            8    /* TDS 7.4 */

/* 字节序 */
#define MSSQL_BIG_ENDIAN            0    /* 大头 */
#define MSSQL_LITTLE_ENDIAN         1    /* 小头 */

/* 客户端发出还是服务端发出 */
#define MSSQL_CLI2SRV               0    /* 从客户端到服务端 */
#define MSSQL_SRV2CLI               1    /* 从服务端到客户端 */

/* TDS各种数据类型长度 */
#define MSSQL_TDS_BYTE_LEN          1    /* BYTE类型长度 */
#define MSSQL_TDS_UCHAR_LEN         1    /* UCHAR类型长度 */
#define MSSQL_TDS_USHORT_LEN        2    /* USHORT类型长度 */
#define MSSQL_TDS_LONG_LEN          4    /* LONG类型长度 */
#define MSSQL_TDS_ULONG_LEN         4    /* ULONG类型长度 */
#define MSSQL_TDS_DWORD_LEN         4    /* DWORD类型长度 */
#define MSSQL_TDS_ULONGLONG_LEN     8    /* ULONGLONG类型长度 */

/* TDS数据类型 */
/* define TYPE_INFO start */
/* FIXEDLENTYPE */
#define TDS_DATA_TYPE_NULL                0x1F  /* Null (no data associated with this type) */
#define TDS_DATA_TYPE_INT1                0x30  /* TinyInt (1 byte data representation) */
#define TDS_DATA_TYPE_BIT                 0x32  /* Bit (1 byte data representation) */
#define TDS_DATA_TYPE_INT2                0x34  /* SmallInt (2 byte data representation) */
#define TDS_DATA_TYPE_INT4                0x38  /* Int (4 byte data representation) */
#define TDS_DATA_TYPE_DATETIM4            0x3A  /* SmallDateTime (4 byte data representation) */
#define TDS_DATA_TYPE_FLT4                0x3B  /* Real (4 byte data representation) */
#define TDS_DATA_TYPE_MONEY               0x3C  /* Money (8 byte data representation) */
#define TDS_DATA_TYPE_DATETIME            0x3D  /* DateTime (8 byte data representation) */
#define TDS_DATA_TYPE_FLT8                0x3E  /* Float (8 byte data representation) */
#define TDS_DATA_TYPE_MONEY4              0x7A  /* SmallMoney (4 byte data representation) */
#define TDS_DATA_TYPE_INT8                0x7F  /* BigInt (8 byte data representation) */

/* define VARLENTYPE start */
/* BYTELEN_TYPE */
#define TDS_DATA_TYPE_GUID                0x24  /* UniqueIdentifier */
#define TDS_DATA_TYPE_INTN                0x26
#define TDS_DATA_TYPE_DECIMAL             0x37  /* Decimal (legacy support) */
#define TDS_DATA_TYPE_NUMERIC             0x3F  /* Numeric (legacy support) */
#define TDS_DATA_TYPE_BITN                0x68
#define TDS_DATA_TYPE_DECIMALN            0x6A  /* Decimal */
#define TDS_DATA_TYPE_NUMERICN            0x6C  /* Numeric */
#define TDS_DATA_TYPE_FLTN                0x6D
#define TDS_DATA_TYPE_MONEYN              0x6E
#define TDS_DATA_TYPE_DATETIMN            0x6F
#define TDS_DATA_TYPE_DATEN               0x28  /* (introduced in TDS 7.3) */
#define TDS_DATA_TYPE_TIMEN               0x29  /* (introduced in TDS 7.3) */
#define TDS_DATA_TYPE_DATETIME2N          0x2A  /* (introduced in TDS 7.3) */
#define TDS_DATA_TYPE_DATETIMEOFFSETN     0x2B  /* (introduced in TDS 7.3) */
#define TDS_DATA_TYPE_CHAR                0x2F  /* Char (legacy support) */
#define TDS_DATA_TYPE_VARCHAR             0x27  /* VarChar (legacy support) */
#define TDS_DATA_TYPE_BINARY              0x2D  /* Binary (legacy support) */
#define TDS_DATA_TYPE_VARBINARY           0x25  /* VarBinary (legacy support) */

/* USHORTLEN_TYPE */
#define TDS_DATA_TYPE_BIGVARBIN           0xA5  /* VarBinary */
#define TDS_DATA_TYPE_BIGVARCHR           0xA7  /* VarChar */
#define TDS_DATA_TYPE_BIGBINARY           0xAD  /* Binary */
#define TDS_DATA_TYPE_BIGCHAR             0xAF  /* Char */
#define TDS_DATA_TYPE_NVARCHAR            0xE7  /* NVarChar */
#define TDS_DATA_TYPE_NCHAR               0xEF  /* NChar */

/* LONGLEN_TYPE */
#define TDS_DATA_TYPE_UDT                 0xF0  /* CLR-UDT (introduced in TDS 7.2) */
#define TDS_DATA_TYPE_XML                 0xF1  /* XML (introduced in TDS 7.2) */
#define TDS_DATA_TYPE_TEXT                0x23  /* Text */
#define TDS_DATA_TYPE_IMAGE               0x22  /* Image */
#define TDS_DATA_TYPE_NTEXT               0x63  /* NText */
#define TDS_DATA_TYPE_SSVARIANT           0x62  /* Sql_Variant (introduced in TDS 7.2) */

/* define VARLENTYPE end */
/* define TYPE_INFO end */

#define APM_TDS_B_VARBYTE         0    /* B_VARBYTE */
#define APM_TDS_US_VARBYTE        1    /* US_VARBYTE */
#define APM_TDS_L_VARBYTE         2    /* L_VARBYTE */

#define APM_TDS_B_VARCHAR         0    /* B_VARCHAR */
#define APM_TDS_US_VARCHAR        1    /* US_VARCHAR */

#define APM_CHARSET_UCS2          "UNICODE"

/* 出参入参标记 */
#define MSSQL_INPUT_PARAM     0
#define MSSQL_OUTPUT_PARAM    1

/* 各个出力field name定义 */
/* request */
#define MSSQL_SQL_STATEMENT             "SQL STATEMENT"
#define MSSQL_SQL_STATEMENT_LEN         13
#define MSSQL_PREPARE_SQL               "PREPARE SQL STATEMENT"
#define MSSQL_PREPARE_SQL_LEN           21
#define MSSQL_RPC_NAME                  "RPC NAME"
#define MSSQL_RPC_NAME_LEN              8
#define MSSQL_RPC_INPUT_PARAM           "RPC INPUT PARAMETER"
#define MSSQL_RPC_INPUT_PARAM_LEN       19
#define MSSQL_RPC_OUTPUT_PARAM          "RPC OUTPUT PARAMETER"
#define MSSQL_RPC_OUTPUT_PARAM_LEN      20
/* response */
#define MSSQL_EFFECT_ROWS               "EFFECT ROWS"
#define MSSQL_EFFECT_ROWS_LEN           12

void sqlserver_node_free(Frlist_node *p_st_node);

void sqlserver_free(void **pp_buffer);

void sqlserver_altmetadata_node_free(Frlist_node *p_st_node);

int sqlserver_data_push(Frlist_header *p_list_header, void *p_data);

int sqlserver_get_varbytes(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , int i_byte_flg
                           , int i_get_value_flg
                           , char **pp_out_bytes
                           , unsigned int *p_ui_out_len);

int sqlserver_get_varchar(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , int i_char_flg
                          , int i_get_value_flg
                          , char **pp_out_char
                          , unsigned int *p_ui_out_len);

int sqlserver_tds_ver_get(Frbyte_Packet *p_st_data
                          , int i_cli_srv_flg
                          , int *p_i_ver);

int sqlserver_value2str(char *p_buffer
                        , unsigned int ui_value_len
                        , int i_value_type
                        , char **pp_output);

int sqlserver_type_info_parse(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , int i_rpc_or_colmeta
                              , int *p_i_min_tds_ver
                              , uint8_t *p_u8_data_type
                              , uint8_t *p_u8_precision
                              , uint8_t *p_u8_scale
                              , int *p_i_partlentype);

int sqlserver_get_type_varbyte(Frbyte_Packet *p_st_data
                              , L7session_sqlserver *p_st_sess
                              , int i_whole_flg
                              , uint8_t uc_data_type
                              , uint8_t ui_precision
                              , uint8_t ui_scale
                              , int i_partlentype
                              , Frdata_field **pp_st_value);

int sqlserver_skip_type_varbyte(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , uint8_t uc_data_type
                               , uint8_t ui_precision
                               , uint8_t ui_scale
                               , int i_partlentype);

int sqlserver_get_rpc_param(Frbyte_Packet *p_st_data
                            , L7session_sqlserver *p_st_sess
                            , int i_whole_flg
                            , int *p_i_may_tds_ver
                            , Frdata_field **pp_st_value
                            , int *p_i_ref_flg);

int sqlserver_skip_rpc_param(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , int *p_i_may_tds_ver
                             , int *p_i_ref_flg);

int sqlserver_parse_prelogin(Conntrack *p_st_conn
                            , L7session_sqlserver_private *p_st_private
                            , Frhash_header *p_st_hash_report
                            , int i_whole_flg
                            , int i_ser_cli_flg);

void sqlserver_frdata_node_free(Frlist_node *p_st_node);

void sqlserver_parameter_free(Frlist_node *p_st_node);

void sqlserver_frdata_free(Frdata_field **pp_st_value);

void sqlserver_destroy_session(L7session_sqlserver **pp_st_session);

void sqlserver_cursor_free(Frlist_node* p_st_node);

void sqlserver_init_fragment(L7_fragment_sqlserver *p_st_fragment);

void sqlserver_destroy_fragment(L7_fragment_sqlserver **pp_st_fragment);

void sqlserver_destroy_request(L7_req_sqlserver **pp_st_request);

L7_req_sqlserver* slqserver_create_request(uint8_t u8_request_type);

void sqlserver_frbindata_destory(Frbindata **pp_st_frbindata);

void sqlserver_frdata_destory(Frdata_field **pp_st_frdata);

void sqlserver_list_free(Frlist_node *p_st_node);

void sqlserver_del_specified_cursor(Frlist_header *p_list_cursor
                                    , long l_cursor_id);

void sqlserver_del_specified_cursor2(Frlist_header *p_list_cursor
                                    , long l_prepare_id);

void sqlserver_init_response(L7_resp_sqlserver *p_st_resp
                            , int i_tds_ver
                            , int i_tds_min_ver
                            , int i_tds_max_ver);

void sqlserver_destroy_response(L7_resp_sqlserver **pp_st_resp);

Mssql_cursor* sqlserver_get_cursor_info(Frlist_header *p_list_cursor
                                       , long l_cursor_id);

int sqlserver_select_chk(const char *p_sql);

Frreport_body_data* sqlserver_new_report_body(Conntrack *p_st_conn
                                             , L7session_sqlserver *p_st_sess);

#endif
